package cal;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import cal.OverAllFrame.EndPanel.ContinueButtonListener;
import cal.OverAllFrame.EndPanel.ReDoButtonListener;
import cal.OverAllFrame.EndPanel.UserRankInfo;
import cal.OverAllFrame.EndPanel.viewRankButtonListener;
import cal.OverAllFrame.RunningPanel.BackButtonListener;
import cal.OverAllFrame.RunningPanel.CompleteButtonListener;
import cal.OverAllFrame.RunningPanel.NextButtonListener;
import cal.OverAllFrame.StartPanel.StartButtonListener;

public// 主体框架
class OverAllFrame extends JFrame {
	TimeThread timer; // 计时器线程
	ArithmeticTest7 ar;// 内部算法
	JPanel headPanel;// 头面板
	JLabel welcomeLabel;// 欢迎信息
	JLabel timeUse; // 用时信息
	StartPanel st;
	String userName;
	RunningPanel rp;
	EndPanel ep;
	Vector<Expression> v;// 存放算式

	public OverAllFrame(String s) {
		super(s);
		userName = JOptionPane.showInputDialog("请输入用户名", "");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.initialize();
		setHeadPanel();
		this.setLocation(400, 100);
		this.setLayout(new BorderLayout());
		this.add(headPanel, BorderLayout.NORTH);
		this.add(st, BorderLayout.CENTER);
		this.setSize(500, 400);
		this.setVisible(true);
	}

	public void initialize()// 初始化控件
	{
		ar = new ArithmeticTest7();
		headPanel = new JPanel();
		welcomeLabel = new JLabel("欢迎!  用户：" + userName);
		st = new StartPanel();
		rp = new RunningPanel();
		ep = new EndPanel();
		timeUse = new JLabel();
	}

	public void setHeadPanel() {
		headPanel.setLayout(new FlowLayout());
		headPanel.add(welcomeLabel);
		headPanel.add(timeUse);
	}

	// 开始面板
	class TimeThread extends Thread // 计时器线程
	{
		int min;
		int sec;
		int millis;
		long oldTime;
		long timeUsed;
		long timeSeted;
		JLabel display;
		boolean stop = false;

		public TimeThread(long timeSeted, JLabel display) {
			oldTime = System.currentTimeMillis();
			this.display = display;
			this.timeSeted = timeSeted;
			// TODO Auto-generated constructor stub
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();

			do {
				timeUsed = System.currentTimeMillis() - oldTime;
				min = (int) (timeUsed / 60000L);
				sec = (int) ((timeUsed % 60000L) / 1000L);
				millis = (int) ((timeUsed % 60000L) % 1000L);
				try {
					sleep(11);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				display.setText("已用时:" + min + ":" + sec + ":" + millis);
				display.setVisible(true);

			} while (timeUsed <= timeSeted && !stop);
			if (!stop)// 如果不是手动停止的就运行complete
				rp.complete();
		}

		public void setStop() {
			stop = true;
		}
	}

	class StartPanel extends JPanel {
		JPanel inputOptionPanel; // 输入选项面板①
		JPanel selectOperatorOptionPanel;// 选择运算符面板②
		JPanel bottomPanel; // 底部面板③

		JLabel inputBitLabel; // 输入位数提示①-1
		JTextField inputBitField; // 输入位数区域①-2
		JLabel inputNumLabel; // 输入题目个数提示①-3
		JTextField inputNumField; // 输入题目个数区域①-4
		JLabel inputTimeLabel; // 输入做题时间提示①-5
		JPanel inputTimePanel; // 输入做题时间区域①-6

		ButtonGroup operatorGroup;
		JRadioButton addButton; // 加法按钮②-1
		JRadioButton minusButton; // 减法按钮②-2
		JRadioButton multiplyButton; // 乘法按钮②-3
		JRadioButton divideButton; // 除法按钮②-4
		JRadioButton mixButton; // 混合运算按钮②-5

		JLabel errorInfo; // 错误信息③-1
		JButton startButton; // 开始按钮③-2

		JTextField inputByminutes; // 输入分钟区域①-6-1
		JLabel printMinute; // 打印提示“分”①-6-2
		JTextField inputByseconds; // 输入秒钟区域①-6-3
		JLabel printSecond; // 打印提示“秒”①-6-4

		public StartPanel() {
			// this.setLayout(new GridLayout(0,1));
			this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			this.initialize();
			this.setInputOptionPanel();
			this.setSelectOperatorOptionPanel();
			this.setBottomPanel();
			this.addStartEvent();
			this.add(inputOptionPanel);
			this.add(selectOperatorOptionPanel);
			this.add(bottomPanel);
		}

		public void initialize() // 初始化所有控件
		{
			inputOptionPanel = new JPanel();
			selectOperatorOptionPanel = new JPanel();
			bottomPanel = new JPanel();
			inputBitLabel = new JLabel("输入题目位数:");
			inputBitField = new JTextField("1");// 默认一位
			inputNumLabel = new JLabel("输入题目个数:");
			inputNumField = new JTextField("10");// 默认产生10题
			operatorGroup = new ButtonGroup();
			addButton = new JRadioButton("加法");
			minusButton = new JRadioButton("减法");
			multiplyButton = new JRadioButton("乘法");
			divideButton = new JRadioButton("除法");
			mixButton = new JRadioButton("混合");
			errorInfo = new JLabel();
			startButton = new JButton("开始做题！");
			inputTimeLabel = new JLabel("输入做题时间:");
			inputTimePanel = new JPanel();
			inputByminutes = new JTextField();
			printMinute = new JLabel("分");
			inputByseconds = new JTextField();
			printSecond = new JLabel("秒");
		}

		// 设置做题时间面板
		public void setInputTimePanel() {
			inputTimePanel.setLayout(new GridLayout(1, 0));
			printMinute.setHorizontalAlignment(SwingConstants.CENTER);
			printSecond.setHorizontalAlignment(SwingConstants.CENTER);
			inputTimePanel.add(inputByminutes);
			inputTimePanel.add(printMinute);
			inputTimePanel.add(inputByseconds);
			inputTimePanel.add(printSecond);
		}

		// 设置输入选项面板
		public void setInputOptionPanel() {
			inputOptionPanel.setLayout(new GridLayout(3, 2));
			inputBitLabel.setHorizontalAlignment(SwingConstants.CENTER);
			inputNumLabel.setHorizontalAlignment(SwingConstants.CENTER);
			inputTimeLabel.setHorizontalAlignment(SwingConstants.CENTER);
			inputOptionPanel.add(inputBitLabel);
			inputOptionPanel.add(inputBitField);
			inputOptionPanel.add(inputNumLabel);
			inputOptionPanel.add(inputNumField);
			inputOptionPanel.add(inputTimeLabel);
			setInputTimePanel();
			inputOptionPanel.add(inputTimePanel);
		}

		// 设置选择运算符面板
		public void setSelectOperatorOptionPanel() {
			// selectOperatorOptionPanel.setLayout(new GridLayout(1,0));
			selectOperatorOptionPanel.setLayout(new BoxLayout(
					selectOperatorOptionPanel, BoxLayout.X_AXIS));

			operatorGroup.add(addButton);
			operatorGroup.add(minusButton);
			operatorGroup.add(multiplyButton);
			operatorGroup.add(divideButton);
			operatorGroup.add(mixButton);
			selectOperatorOptionPanel.add(addButton);
			selectOperatorOptionPanel.add(minusButton);
			selectOperatorOptionPanel.add(multiplyButton);
			selectOperatorOptionPanel.add(divideButton);
			selectOperatorOptionPanel.add(mixButton);
		}

		public void setBottomPanel() {
			bottomPanel.setLayout(new GridLayout(0, 1));
			bottomPanel.add(errorInfo);
			bottomPanel.add(startButton);
		}

		// 添加开始按钮处理事件
		public void addStartEvent() {
			startButton.addActionListener(new StartButtonListener());
		}

		// 内部类，实现开始事件
		class StartButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent e) {
				ar.v.clear();// 清空向量
				char operator = '+';// 默认加法
				if (minusButton.isSelected()) {
					operator = '-';
				} else if (multiplyButton.isSelected()) {
					operator = '*';
				} else if (divideButton.isSelected()) {
					operator = '/';
				} else if (mixButton.isSelected())// 混合运算
				{
					operator = '.';
				}
				try {
					int numOfEquation = Integer.parseInt(inputNumField
							.getText());
					int bigOfEquation = Integer.parseInt(inputBitField
							.getText());
					int minSeted = Integer.parseInt(inputByminutes.getText());
					int secSeted = Integer.parseInt(inputByseconds.getText());
					long millisSeted = (minSeted * 60 + secSeted) * 1000;
					timer = new TimeThread(millisSeted, timeUse);
					timer.start();
					if (numOfEquation > 100)
						throw new NumberTooBigException("这么多题，你做的完吗？");
					rp.getTotalPage(numOfEquation);// 获得总页数
					rp.setPageLabel();
					if (bigOfEquation > 9)
						throw new NumberTooBigException("输入的位数太高了");
					else if (bigOfEquation == 0)
						throw new NumberTooBigException("位数不能为0");
					while (ar.v.size() < numOfEquation) {
						ar.produceExpression(bigOfEquation, operator);
					}
					OverAllFrame.this.v = ar.v;
					rp.writeEquationToLabel();

					OverAllFrame.this.st.setVisible(false);// 开始面板调为不可见
					OverAllFrame.this.add(rp, BorderLayout.CENTER);
					OverAllFrame.this.setVisible(true);// 更新窗口
					OverAllFrame.this.rp.setVisible(true);// 显示做题面板
				} catch (NumberFormatException ex) {
					errorInfo.setText("输入数据类型错误！你必须输入数值数据!,请重新输入：");
				} catch (NumberTooBigException ex) {
					errorInfo.setText(ex.getMessage());
				} catch (Exception ex) {

				}

			}
		}
	}

	// 做题中的面板
	class RunningPanel extends JPanel {
		JPanel contentPanel;// 存放题目和答案①
		JPanel buttonsPanel;// 存放按钮②
		JLabel pageLabel; // 显示当前页/所有页
		Vector<JLabel> expressionGroup;// 显示题目①-1
		Vector<JTextField> answerGroup;// 存放答案①-2

		JButton backButton;// 上一页②-1
		JButton nextButton;// 下一页②-2
		JButton completeButton; // 完成②-3

		int totalPage = 1; // 总页数
		int currentPage = 1;// 当前页

		public RunningPanel() {
			this.setLayout(new BorderLayout());
			this.initialize();
			this.addItem();
			this.setContentPanel();
			this.setButtonsPanel();
		}

		public void initialize()// 初始化
		{
			contentPanel = new JPanel();
			buttonsPanel = new JPanel();
			pageLabel = new JLabel();
			expressionGroup = new Vector<JLabel>();
			answerGroup = new Vector<JTextField>();
			for (int i = 0; i < 10; i++) {
				expressionGroup.add(new JLabel());
				answerGroup.add(new JTextField());
			}
			backButton = new JButton("上一页");
			nextButton = new JButton("下一页");
			completeButton = new JButton("完成!");
			backButton.addActionListener(new BackButtonListener());
			nextButton.addActionListener(new NextButtonListener());
			completeButton.addActionListener(new CompleteButtonListener());

		}

		public void setContentPanel() {
			contentPanel.setLayout(new GridLayout(6, 2));
			for (int i = 0; i < 10; i++) {
				contentPanel.add(expressionGroup.get(i));
				contentPanel.add(answerGroup.get(i));
			}
		}

		public void setPageLabel() {
			pageLabel.setText("页码" + currentPage + '/' + totalPage);
		}

		public void setButtonsPanel() {
			buttonsPanel.add(backButton);
			buttonsPanel.add(nextButton);
			buttonsPanel.add(completeButton);
		}

		public void writeEquationToLabel()// 写入算式
		{
			// 因为只有十个标签，n道题目，不能一一对应，下面是标签要加上的数和题目号对应
			int numNeededToAdd = (currentPage - 1) * 10;
			for (int i = 0; i < 10; i++) {
				if (i + numNeededToAdd >= v.size())// 没有更多题目了
				{
					expressionGroup.get(i)
							.setText(String.format("%17s", "N/A"));
				} else {
					String temp = String.format("%5d%5s%5d%5s", v.get(i
							+ numNeededToAdd).a,
							v.get(i + numNeededToAdd).operator, v.get(i
									+ numNeededToAdd).b, "=");
					expressionGroup.get(i).setText(temp);
				}
			}
		}

		public void addItem()// 添加控件
		{
			this.add(pageLabel, BorderLayout.NORTH);
			this.add(contentPanel, BorderLayout.CENTER);
			this.add(buttonsPanel, BorderLayout.SOUTH);
		}

		public void getTotalPage(int num)// 获得总页数
		{
			totalPage = num / 10 + (num % 10 == 0 ? 0 : 1);
		}

		// 设置当前页为1，重做和继续的时候用到
		public void setCurrentPageToOne() {
			currentPage = 1;
		}

		public void writeInputToVector() throws Exception {
			// 因为只有十个标签，n道题目，不能一一对应，下面是标签要加上的数和题目号对应
			int numNeededToAdd = (currentPage - 1) * 10;
			for (int i = 0; i < 10 && i + numNeededToAdd < v.size(); i++) {
				try {
					if (!answerGroup.get(i).getText().equals(""))// 如果不是啥也没写的话
					{
						v.get(i + numNeededToAdd).d = Integer
								.parseInt(answerGroup.get(i).getText());
						if (v.get(i + numNeededToAdd).d == v.get(i
								+ numNeededToAdd).c)
							v.get(i + numNeededToAdd).is_right = true;
					}
					// 否则就是默认的-1

				} catch (NumberFormatException e) {
					answerGroup.get(i).setText("输入数据类型错误！请重新输入：");
					throw e;// 必须这么写才能终止。。
				} catch (Exception e) {
					answerGroup.get(i).setText("未知错误！请重新输入：");
					throw e;// 必须这么写才能终止。。
				}
			}
		}

		public void clearAnswer()// 清空答案
		{
			for (int i = 0; i < answerGroup.size(); i++) {
				answerGroup.get(i).setText("");
			}
		}

		// 写入答案进输入区，还原上下页做过的答案用
		public void writeAnswerTofield() {
			// 因为只有十个标签，n道题目，不能一一对应，下面是标签要加上的数和题目号对应
			int numNeededToAdd = (currentPage - 1) * 10;
			for (int i = 0; i < 10 && i + numNeededToAdd < v.size(); i++) {
				if (v.get(i + numNeededToAdd).d != -1)// 说明有输入过值
				{
					answerGroup.get(i).setText(
							Integer.toString(v.get(i + numNeededToAdd).d));
				}
			}
		}

		public void complete()// 完成做题，用户点击完成或者 是时间到了
		{
			try {
				// 因为第一句可能会产生异常，不过在句中已经处理，这里加上
				// try是让它停止进入下一页
				timer.setStop();// 计时器线程停止
				OverAllFrame.this.rp.writeInputToVector();// 写入答案进向量
				OverAllFrame.this.ar.writeInfo(v.size(), userName);
				OverAllFrame.this.rp.setVisible(false);// 设置做题界面不可见
				OverAllFrame.this.ep.setDisplayAnswer(); // 设置要显示的结果
				OverAllFrame.this.add(ep, BorderLayout.CENTER);
				OverAllFrame.this.setVisible(true);
				OverAllFrame.this.ep.setVisible(true);// 显示答案面板

			} catch (Exception e) {
				// do nothing
			}

		}

		class CompleteButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent ae) {
				complete();
			}
		}

		class BackButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent ae) {

				if (currentPage > 1) {
					try {
						writeInputToVector();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}// 保存上页数据
					clearAnswer();// 删除上页答案
					currentPage--;
					setPageLabel();// 更新页码
					writeEquationToLabel();// 读入下页算式
					writeAnswerTofield();// 读入下页已填写答案
					RunningPanel.this.setVisible(true);// 更新窗口
				}
			}
		}

		class NextButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent ae) {
				if (currentPage < totalPage) {
					try {
						writeInputToVector();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					clearAnswer();// 删除上页答案
					currentPage++;
					setPageLabel();
					writeEquationToLabel();
					writeAnswerTofield();
					RunningPanel.this.setVisible(true);
				}
			}
		}

	}

	// 显示结果面板
	class EndPanel extends JPanel {
		JScrollPane displayArea;// 显示区域
		JPanel bottomArea; // 底部区域，存放按钮
		JTextArea displayAnswer;// 显示答案和评分
		JTextArea displayRank; // 显示排名和得分

		JButton reDoButton;// 重做
		JButton continueButton;// 继续练习
		JButton viewRankButton;// 查看排名

		Font answerFont; // 字体属性
		boolean isRankViewed = false;// 是否查看过排名
		boolean alreadyWrite = false;// 已经写入排名信息

		public EndPanel() {
			this.setLayout(new BorderLayout());// 边界布局
			this.initialize();
			this.setBottomArea();
			this.addItem();

		}

		public void initialize()// 初始化
		{
			answerFont = new Font("宋体", Font.PLAIN, 15);
			displayAnswer = new JTextArea();
			displayAnswer.setFont(answerFont);// 设置字体
			displayArea = new JScrollPane(displayAnswer);
			displayRank = new JTextArea();
			displayRank.setFont(answerFont);
			bottomArea = new JPanel();
			reDoButton = new JButton("重做一遍");
			continueButton = new JButton("继续练习");
			viewRankButton = new JButton("查看排名");
			reDoButton.addActionListener(new ReDoButtonListener());
			continueButton.addActionListener(new ContinueButtonListener());
			viewRankButton.addActionListener(new viewRankButtonListener());

		}

		public void setDisplayAnswer()// 添加答案
		{
			displayAnswer.setEditable(false);// 只显示答案，不可编辑
			String temp;
			int score = 0;
			temp = (String.format("%5s%5s%5s%5s%5s%10s%5s", "", "", "", "",
					"正确答案", "你的答案", "判断"))
					+ "\r\n";
			displayAnswer.append(temp);
			for (int i = 0; i < v.size(); i++) {
				temp = (String.format("%5d%5s%5d%5s%10d%10d%10s", v.get(i).a, v
						.get(i).operator, v.get(i).b, "=", v.get(i).c,
						v.get(i).d, (v.get(i).is_right ? "正确" : "错误")))
						+ "\r\n";
				displayAnswer.append(temp);
				if (v.get(i).is_right) {
					score += 100.0 / v.size();
				}
			}
			temp = ("你的总分：" + score + "\r\n");
			displayAnswer.append(temp);

		}

		public void setDisplayRank() {
			if (alreadyWrite)// 如果已经执行过了
				return;
			alreadyWrite = true;
			viewRankButton.setText("查看答案");
			displayRank.setEditable(false);
			FileReader file;
			BufferedReader bf;
			String tempString;// 临时用户名
			String tempIntedString;// 临时分数的String形式
			double tempInt;// 临时分数
			// 用户名和用户最高分的映射关系
			HashMap<String, Double> map = new HashMap<String, Double>();
			try {
				file = new FileReader("UserNameAndScore.data");
				if (!file.ready()) {
					displayRank.setText("无有效数据");
				}
				bf = new BufferedReader(file);

				tempString = bf.readLine();
				tempIntedString = bf.readLine();
				while (tempString != null && tempIntedString != null) {
					tempInt = Double.parseDouble(tempIntedString);
					// 确保显示的为每个人历史所得最高分
					if (!(map.containsKey(tempString) && tempInt <= map
							.get(tempString))) {
						map.put(tempString, tempInt);
					}
					tempString = bf.readLine();
					tempIntedString = bf.readLine();
				}
			} catch (Exception e) {
				System.out.println(e.getMessage());
				viewRankButton.setText("文件异常");
			}
			Vector<UserRankInfo> v = new Vector<UserRankInfo>();
			Iterator<String> it = map.keySet().iterator();
			UserRankInfo temp;

			while (it.hasNext()) {
				tempString = it.next();
				temp = new UserRankInfo(tempString, map.get(tempString));
				v.add(temp);
			}
			Collections.sort(v, new UserRankInfo());
			int rank = 1;
			displayRank.append(String.format("%10s%10s%10s", "排名", "用户名", "得分")
					+ "\r\n");
			for (UserRankInfo u : v) {
				displayRank.append(String.format("%10d%15s%15f", rank++,
						u.userName, u.score)
						+ "\r\n");
			}

		}

		public void setBottomArea()// 添加底部按钮
		{
			bottomArea.setLayout(new FlowLayout());
			bottomArea.add(reDoButton);
			bottomArea.add(continueButton);
			bottomArea.add(viewRankButton);
		}

		public void addItem()// 添加组件
		{

			this.add(displayArea, BorderLayout.CENTER);
			this.add(bottomArea, BorderLayout.SOUTH);
		}

		public void recoverAnswerArea()// 恢复答案区域
		{
			viewRankButton.setText("查看排名");
			displayArea.setViewportView(displayAnswer);
			displayAnswer.setVisible(true);
			isRankViewed = false;
		}

		class ReDoButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent ae) {
				OverAllFrame.this.rp.setCurrentPageToOne();// 设置当前页码 为1
				OverAllFrame.this.ep.setVisible(false);// 隐藏结果面板
				OverAllFrame.this.rp.clearAnswer();// 先清除做题面板的内容
				OverAllFrame.this.rp.setVisible(true);// 显示做题面板
				if (isRankViewed)
					recoverAnswerArea();
			}
		}

		class ContinueButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent ae) {
				OverAllFrame.this.rp.setCurrentPageToOne();// 设置当前页码 为1
				OverAllFrame.this.rp.clearAnswer();// 先清除做题面板的内容
				OverAllFrame.this.ep.setVisible(false);// 隐藏结果面板
				OverAllFrame.this.st.setVisible(true);// 显示开始面板
				if (isRankViewed)
					recoverAnswerArea();

			}
		}

		class viewRankButtonListener implements ActionListener {
			public void actionPerformed(ActionEvent e) {
				if (!isRankViewed) {

					setDisplayRank();// 写入排名信息
					displayAnswer.setVisible(false);
					displayArea.setViewportView(displayRank);
					displayRank.setVisible(true);
					isRankViewed = true;
				} else {
					recoverAnswerArea();
				}

			}
		}

		// 实现比较接口的用户排名类
		class UserRankInfo implements Comparator<UserRankInfo> {
			public String userName;
			public double score;

			public UserRankInfo(String userName, double score) {
				this.userName = userName;
				this.score = score;
			}

			public UserRankInfo() {
				// none
			}

			public int compare(UserRankInfo arg0, UserRankInfo arg1) {
				if (arg0.score < arg1.score)
					return 1;
				else if (arg0.score > arg1.score)
					return -1;
				return 0;
			}

		}
	}
}